import mutil
from Tkinter import *
import shellclasses
from importpyrind import pyrind

#todo-- allow reversing, keeping track of default values

class FormItem_Base():
	labelText = None
	propertyName = None
	fnshellobject = None
	fncallbackrefresh = None
	def __init__(self, labelText, propertyName):
		self.labelText = labelText
		self.propertyName = propertyName
		
	def renderWidget(self, master, nRow):
		lbl = Label(master, text=self.labelText)
		widget = self.createWidget(master)
		lbl.grid(row=nRow, column=0, sticky=E)
		widget.grid(row=nRow, column=1)
		
	def createWidget(self, master):
		raise 'not implemented'
	def updateInfo(self):
		raise 'not implemented'

#just force them to click the ID thing...
#~ class FormItem_EntryName(FormItem_Base):
	#~ def createWidget(self, master):
		#~ widget = Entry(master)
		#~ widget.config(text=self.shellobject.widgetName)
		#~ self.var=StringVar()
		#~ self.trace(self.callback)
		#~ widget.config(var=self.var)
	#~ def callback(self, *args):
		#~ #TODO: validate isn't the same as another id name.
		#~ #Set the value whenever changes!
		#~ v = self.var.get()
		#~ v = makeIdentifier(v) #remove alphanums
		#~ if not v: v='untitled'
		#~ self.var.set(v)
		#~ self.shellobject.pyrindProperties[self.propertyName] = v
class FormItem_EntryName(FormItem_Base):
	callback = None
	def createWidget(self, master):
		self.widget = Label(master, text='')
		self.widget.bind('<Button-1>', lambda e=None: self.callback() or self.updateInfo()) #todo: update hack.
		return self.widget
	def updateInfo(self):
		self.widget.config(text=self.fnshellobject().widgetName)
		
class FormItem_Entry(FormItem_Base):
	def createWidget(self, master):
		widget = Entry(master)
		self.var=StringVar()
		self.var.trace('w',self.callback)
		widget.config(textvariable=self.var)
		return widget
	def updateInfo(self):
		self.var.set( str(self.fnshellobject().pyrindProperties.get(self.propertyName,'')))
	def callback(self, *args):
		#Set the value whenever changes!
		v = self.var.get()
		
		#~ if not v: 
		#Todo: allow this. we'd need a way to keep track of default values, I think
			#~ #remove property from dict, to get default value
			#~ if self.propertyName in self.fnshellobject().pyrindProperties:
				#~ del self.fnshellobject().pyrindProperties[self.propertyName]
		#~ else:
		self.fnshellobject().pyrindProperties[self.propertyName] = v
		#set the item actually, to see difference:
		print self.propertyName
		self.fncallbackrefresh()
		
class FormItem_EntryNumeric(FormItem_Entry):
	def callback(self, *args):
		#Set the value whenever changes!
		v = self.var.get()
		try: int(v)
		except: return False
		
		self.fnshellobject().pyrindProperties[self.propertyName] = int(v)
		self.fncallbackrefresh()


class FormItem_ColorSelect(FormItem_Base):
	def createWidget(self, master):
		widget = Button(master)
		widget.config(text=' ',bg='black', command=self.onclick)
		return widget
	def onclick(self):
		newcolor = pyrind.dialog.ask_color()
		if not newcolor: return
		self.fnshellobject().pyrindProperties[self.propertyName] = newcolor
		self.fncallbackrefresh()
	def updateInfo(self):
		#todo: update the color?
		pass


		
class FormItem_Options(FormItem_Base):
	optionList = None
	def __init__(self, labelText, propertyName, optionList):
		self.labelText = labelText
		self.propertyName = propertyName
		self.optionList = (' '*8,) + optionList
	def createWidget(self, master):
		self.var=StringVar()
		self.var.trace('w',self.callback)
		widget = OptionMenu(master, self.var, *self.optionList)
		return widget
		
	def updateInfo(self):
		self.var.set( str(self.fnshellobject().pyrindProperties.get(self.propertyName,' '*8)))
	def callback(self, *args):
		v = self.var.get()
		if v!=' '*8:
			self.fnshellobject().pyrindProperties[self.propertyName] = v
			#set the item actually, to see difference:
			self.fncallbackrefresh()
	
def createFrames(appobj, master):
	frames = {}
	frames['RWindow']= makeAFrame(appobj, master,[ 
		FormItem_ColorSelect('Bgcolor', 'bgcolor'),
		FormItem_Options('Borderstyle', 'borderstyle', optsBorderstyle),
		FormItem_EntryNumeric('Borderwidth', 'borderwidth'),
		FormItem_Entry('Title', 'title'),
		], nameField=False)
	frames['RInput']= makeAFrame(appobj, master,[ 
		FormItem_Entry('Text', 'text'),
		FormItem_Options('Borderstyle', 'borderstyle', optsBorderstyle),
		])
	frames['RButton']= makeAFrame(appobj, master,[ 
		FormItem_Entry('Text', 'text'),
		FormItem_EntryNumeric('Height (lines)', 'height'),
		FormItem_EntryNumeric('Width (chars)', 'width'),
		FormItem_ColorSelect('Color', 'color'),
		FormItem_ColorSelect('Bgcolor', 'bgcolor'),
		FormItem_Options('Borderstyle', 'borderstyle', optsBorderstyle),
		#border width
		FormItem_EntryNumeric('Wrapwidth', 'wrapwidth'),
		])
	frames['RCheckbox']= makeAFrame(appobj, master,[ 
		FormItem_Entry('Text', 'text'),
		FormItem_EntryNumeric('Height (lines)', 'height'),
		FormItem_EntryNumeric('Width (chars)', 'width'),
		FormItem_ColorSelect('Color', 'color'),
		FormItem_ColorSelect('Bgcolor', 'bgcolor'),
		FormItem_Options('Borderstyle', 'borderstyle', optsBorderstyle),
		#border width
		FormItem_EntryNumeric('Wrapwidth', 'wrapwidth'),
		])
	frames['RField']= makeAFrame(appobj, master,[ 
		FormItem_Entry('Text', 'text'),
		FormItem_EntryNumeric('Height (lines)', 'height'),
		FormItem_EntryNumeric('Width (chars)', 'width'),
		FormItem_Options('Wrap', 'wrap', optsWrap),
		FormItem_ColorSelect('Color', 'color'),
		FormItem_ColorSelect('Bgcolor', 'bgcolor'),
		FormItem_Options('Borderstyle', 'borderstyle', optsBorderstyle),
		#border width
		])
	frames['RLabel']= makeAFrame(appobj, master,[ 
		FormItem_Entry('Text', 'text'),
		FormItem_EntryNumeric('Height (lines)', 'height'),
		FormItem_EntryNumeric('Width (chars)', 'width'),
		FormItem_ColorSelect('Color', 'color'),
		FormItem_ColorSelect('Bgcolor', 'bgcolor'),
		FormItem_Options('Borderstyle', 'borderstyle', optsBorderstyle),
		#border width
		FormItem_EntryNumeric('Wrapwidth', 'wrapwidth'),
		])
	frames['RListbox']= makeAFrame(appobj, master,[ 
		FormItem_EntryNumeric('Height (lines)', 'height'),
		FormItem_EntryNumeric('Width (chars)', 'width'),
		FormItem_ColorSelect('Color', 'color'),
		FormItem_ColorSelect('Bgcolor', 'bgcolor'),
		FormItem_Options('Borderstyle', 'borderstyle', optsBorderstyle),
		#border width
		])
	#TODO: RSlider
	#need way to have Range set.
	
	for frame in frames:
		if frame!='RWindow':
			frames[frame].forget()
	return frames
		
def makeAFrame(appobj, master, data, nameField=True):
	#TODO: think about the circular references here...
	fr = Frame(master)
	fr.pack(fill=BOTH, expand=1) #they all begin packed.
	fnGet= appobj.getSelected
	fnCallbackRefresh = appobj.updateSelectionProps
	#first, make the id one.
	if nameField:
		item = FormItem_EntryName('name',None)
		item.callback = appobj.onclickContextSetid
		data.insert(0, item)
	row=0
	for prop in data:
		prop.fnshellobject = fnGet; prop.fncallbackrefresh = fnCallbackRefresh
		prop.renderWidget(fr, row)
		row+=1
	fr._propObjects = data
	return fr

optsBorderstyle=('sunken','raised','groove','ridge','flat')
optsWrap=('none','char','word')



	